package cn.tedu.blog.server.service.impl;

import cn.tedu.blog.server.exception.ServiceException;
import cn.tedu.blog.server.mapper.RoleMapper;
import cn.tedu.blog.server.pojo.dto.RoleAddNewDTO;
import cn.tedu.blog.server.pojo.entity.Role;
import cn.tedu.blog.server.pojo.vo.RoleListVO;
import cn.tedu.blog.server.service.IRoleService;
import cn.tedu.blog.server.utils.JsonPage;
import cn.tedu.blog.server.utils.ServiceCode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @Author: 雷茂林
 * @Date:2022/7/17 17:02
 * @Description: 用户管理-业务逻辑实现类
 */
@Slf4j
@Service
public class RoleServiceImpl implements IRoleService {

    @Autowired
    private RoleMapper roleMapper;


    @Autowired
    private RedisTemplate redisTemplate;


    // 开发规范标准：为了降低Redis的Key拼写错误的风险，我们都会定义常量
    public static final String ROLE_LIST_KEY = "roleList";



    @Override
    public void creatRole(RoleAddNewDTO roleAddNewDTO) {
        log.debug("准备开始处理创建角色的业务，参数：{}",roleAddNewDTO);

        if (roleAddNewDTO != null && roleAddNewDTO.getName().trim().length()<= 0){
            throw new ServiceException(ServiceCode.ERR_INSERT, "角色名称不能为空！");
        }

        if (roleAddNewDTO != null && roleMapper.isUpdateName(0L,roleAddNewDTO.getName())>0){
            throw new ServiceException(ServiceCode.ERR_CONFLICT,"角色名称【"+roleAddNewDTO.getName()+"】已被使用");
        }
        Role role = new Role();
        BeanUtils.copyProperties(roleAddNewDTO,role);
        LocalDateTime now = LocalDateTime.now();
        role.setGmtCreate(now);
        role.setGmtModified(now);

        if (roleMapper.creatRole(role)<=0){
            throw new ServiceException(ServiceCode.ERR_INSERT,"创建角色失败，请稍后再试！");
        }

        redisTemplate.delete(ROLE_LIST_KEY);
    }



    @Override
    public void deleteById(Long roleId) {
        log.debug("准备开始处理【删除角色】的业务，参数：{}",roleId);
        if (roleMapper.isRoleById(roleId)<=0){
            throw new ServiceException(ServiceCode.ERR_NOT_FOUND,"需要删除的角色不存在");
        }
        if (roleMapper.deleteById(roleId)<=0){
            throw new ServiceException(ServiceCode.ERR_DELETE,"删除失败，请稍后再试");
        }

        roleMapper.clearMenuByRoleId(roleId);
        roleMapper.clearUserRoleById(null,roleId);

        redisTemplate.delete(ROLE_LIST_KEY);
    }



    @Override
    public int deleteByIds(List<Long> ids) {
        log.debug("准备开始处理【批量删除角色】的业务，参数：{}",ids);

        for (Long id : ids) {
            roleMapper.clearMenuByRoleId(id);
            roleMapper.clearUserRoleById(null,id);
        }

        redisTemplate.delete(ROLE_LIST_KEY);
        return roleMapper.deleteByIds(ids);


    }



    @Override
    public void updateById(RoleAddNewDTO roleAddNewDTO) {
        log.debug("准备开始处理【修改角色】的业务，参数：{}",roleAddNewDTO);
        if (roleAddNewDTO!=null){
            if (roleMapper.isUpdateName(roleAddNewDTO.getId(),roleAddNewDTO.getName())>0){
                throw new ServiceException(ServiceCode.ERR_CONFLICT,"角色名称【"+roleAddNewDTO.getName()+"】已被使用");
            }
        }
        LocalDateTime now = LocalDateTime.now();
        roleAddNewDTO.setGmtModified(now);
        if (roleMapper.updateById(roleAddNewDTO)<=0){
            throw new ServiceException(ServiceCode.ERR_UPDATE,"修改角色失败，请稍后再试！");
        }
    }




    @Override
    public int getCountAll(RoleListVO roleListVO) {
        log.debug("准备开始处理条件查询结果集数量的业务，参数：{}", roleListVO);
        return roleMapper.getCountAll(roleListVO);
    }


    // 回显角色信息
    @Override
    public RoleListVO getBackFillById(Long id) {
        log.debug("准备开始处理【数据回填】的业务，参数：{}", id);
        return roleMapper.getBackFillById(id);
    }



    // 根据用户id回显该用户拥有的角色id
    @Override
    public Long[] getBackFillByUserId(Long id) {
        log.debug("准备开始处理【数据回填】的业务，参数：{}", id);
        return roleMapper.getBackFillByUserId(id);
    }



    // 查询角色列表
    @Override
    public List<RoleListVO> getRoleEcho() {
        if (redisTemplate.hasKey(ROLE_LIST_KEY)) {
            log.debug("即将向redis中查询角色列表..");
            return (List<RoleListVO>) redisTemplate.opsForValue().get(ROLE_LIST_KEY);
        }

        log.debug("即将向数据库中查询角色列表..");
        List<RoleListVO> listRole = roleMapper.listRoleEcho();
        redisTemplate.opsForValue().set(ROLE_LIST_KEY, listRole,24, TimeUnit.HOURS);

        return listRole;
    }



    @Override
    public JsonPage<RoleListVO> listByKeyword(RoleListVO roleListVO) {
        PageHelper.startPage(roleListVO.getPageNum(),roleListVO.getPageSize());
        log.debug("准备开始处理条件分页查询菜单的业务，参数：{}",roleListVO);
        LocalDateTime start = roleListVO.getUpdateTimeStart();
        LocalDateTime end = roleListVO.getUpdateTimeEnd();
        if (start!=null  && end!=null ) {
            if (end.isBefore(start)){
                LocalDateTime temp = start;
                roleListVO.setUpdateTimeStart(end);
                roleListVO.setUpdateTimeEnd(temp);
            }
        }
        return JsonPage.restPage(new PageInfo<>(roleMapper.listByKeyword(roleListVO)));
    }



    @Override
    public List<Long> roleMenuById(Long id) {
        log.debug("准备开始处理根据菜单等级查询对应的菜单信息，参数：{}",id);
        return roleMapper.roleMenuById(id);
    }



    @Override
    public void updateMenuByRoleId(Long roleId,Long[] menuTreeArray){

            if (menuTreeArray==null || menuTreeArray.length<=0){
                roleMapper.clearMenuByRoleId(roleId);
                return;
            }
            // 删除角色权限
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime gmtCreate = now;
            LocalDateTime gmtModified = now;
            roleMapper.clearMenuByRoleId(roleId);
            // 重新赋予权限
            roleMapper.createMenuByRoleId(
                    roleId,
                    menuTreeArray,
                    gmtCreate,
                    gmtModified);

    }


}

